import 'dart:convert';

import 'package:demo/common/utils/log_util.dart';
import 'package:shared_preferences/shared_preferences.dart';

/// 属性存储封装使用kv形式
class SpUtil {
  /// 单例
  static final SpUtil _instance = SpUtil._();

  /// 工厂构造函数 返回单例
  factory SpUtil() => _instance;

  SpUtil._();

  late final SharedPreferences _prefs;

  /// 获取完整的键名（键+后缀）
  String _getFullKey(String key, {String? suffix}) {
    return suffix != null ? key + suffix : key;
  }

  Future<void> init() async {
    _prefs = await SharedPreferences.getInstance();
  }

  Future<bool> remove(String key, {String? suffix}) async {
    try {
      return await _prefs.remove(_getFullKey(key, suffix: suffix));
    } catch (e, st) {
      Log.h(
        e,
        stackTrace: st,
        msg: "删除键 ${_getFullKey(key, suffix: suffix)} 失败",
      );
      return false;
    }
  }

  Future<bool> clear() async {
    try {
      return await _prefs.clear();
    } catch (e, st) {
      Log.h(e, stackTrace: st, msg: "清空 SharedPreferences 失败");
      return false;
    }
  }

  /// 获取所有键
  Set<String> getAllKeys({String? key}) {
    final keys = _prefs.getKeys();
    if (key != null) {
      return keys.where((it) => it.startsWith(key)).toSet();
    }
    return keys;
  }

  /// Set a value for the given key with generic type support
  Future<bool> set<T>(String key, T value, {String? suffix}) async {
    try {
      final prefs = _prefs;
      final fullKey = _getFullKey(key, suffix: suffix);
      if (T == String) {
        return await prefs.setString(fullKey, value as String);
      } else if (T == int) {
        return await prefs.setInt(fullKey, value as int);
      } else if (T == double) {
        return await prefs.setDouble(fullKey, value as double);
      } else if (T == bool) {
        return await prefs.setBool(fullKey, value as bool);
      } else if (T == List<String>) {
        return await prefs.setStringList(fullKey, value as List<String>);
      } else if (T == Map<String, dynamic>) {
        return await prefs.setString(fullKey, jsonEncode(value));
      }
      throw Exception('不支持的类型: $T');
    } catch (e, st) {
      Log.h(
        e,
        stackTrace: st,
        msg: "设置键 ${_getFullKey(key, suffix: suffix)} 的值失败",
      );
      return false;
    }
  }

  /// Get a value for the given key with generic type support
  T get<T>(String key, {T? defaultValue, String? suffix}) {
    try {
      final prefs = _prefs;
      final fullKey = _getFullKey(key, suffix: suffix);
      if (T == String) {
        return (prefs.getString(fullKey) ?? defaultValue ?? '') as T;
      } else if (T == int) {
        return (prefs.getInt(fullKey) ?? defaultValue ?? 0) as T;
      } else if (T == double) {
        return (prefs.getDouble(fullKey) ?? defaultValue ?? 0.0) as T;
      } else if (T == bool) {
        return (prefs.getBool(fullKey) ?? defaultValue ?? false) as T;
      } else if (T == List<String>) {
        return (prefs.getStringList(fullKey) ?? defaultValue ?? const []) as T;
      } else if (T == Map<String, dynamic>) {
        final String? jsonString = prefs.getString(fullKey);
        return (jsonString != null ? jsonDecode(jsonString) : defaultValue ?? {}) as T;
      }
      throw Exception('不支持的类型: $T');
    } catch (e, st) {
      Log.h(
        e,
        stackTrace: st,
        msg: "获取键 ${_getFullKey(key, suffix: suffix)} 的值失败",
      );
      return defaultValue as T;
    }
  }
}

/// 来源 https://blog.csdn.net/qq_16696763/article/details/127488881
/// 看SharedPreferences 读取时已经用了缓存 所以这里把缓存部分删除
/// SharedPreferences封装
/// test() {
///   "test".spValue("");
///   SpValue("test", "");
/// }
class SpValue<T> {
  /// key
  final String key;

  /// 默认值
  final T defaultValue;

  /// 默认后缀
  String? defaultSuffix;

  /// 初始化
  SpValue({required this.key, required this.defaultValue, this.defaultSuffix});

  /// 取值
  T getValue({T? defaultValue, String? suffix}) {
    return SpUtil().get(key, defaultValue: defaultValue ?? this.defaultValue, suffix: suffix ?? defaultSuffix);
  }

  /// 设置值
  Future<bool> setValue(T newValue, {String? suffix}) async {
    return SpUtil().set(key, newValue, suffix: suffix ?? defaultSuffix);
  }

  /// 清除
  Future<bool> remove({String? suffix}) async {
    return SpUtil().remove(key, suffix: suffix ?? defaultSuffix);
  }

  /// 清除所有此key开头
  Future<void> removeAll() async {
    var allKeys = SpUtil().getAllKeys(key: key);
    for (var element in allKeys) {
      await SpUtil().remove(element);
    }
  }

  /// 获取所有此key开头，返回Map以key作为键
  Map<String, T> getAll({T? defaultValue}) {
    var allKeys = SpUtil().getAllKeys(key: key);
    return Map.fromEntries(
      allKeys.map((e) => MapEntry(e, SpUtil().get(e, defaultValue: defaultValue ?? this.defaultValue))),
    );
  }
}

/// sp 存/取对象
class SpObj<T> extends SpValue<T?> {
  /// json转对象
  final T? Function(String json) fromJson;

  /// 对象转json
  final String Function(T obj) toJson;

  /// 初始化
  SpObj(String key, {super.defaultValue, required this.fromJson, required this.toJson, super.defaultSuffix})
    : super(key: key);

  /// 取值
  @override
  T? getValue({T? defaultValue, String? suffix}) {
    String json = SpUtil().get<String>(key, suffix: suffix ?? defaultSuffix);
    return json.isEmpty ? defaultValue ?? this.defaultValue : fromJson(json);
  }

  /// 设置值
  @override
  Future<bool> setValue(T? newValue, {String? suffix}) async {
    if (newValue == null) {
      return await remove(suffix: suffix);
    }
    return SpUtil().set(key, toJson(newValue), suffix: suffix ?? defaultSuffix);
  }
}

/// 感觉有点鸡肋可读性差 不用了
extension ExSpValue on String {
  /// String 转 SpValue
  SpValue<T> spValue<T>(T defValue, {String? defaultSuffix}) {
    return SpValue(key: this, defaultValue: defValue, defaultSuffix: defaultSuffix);
  }

  /// String 转 SpObj
  SpObj<T> spObj<T>({
    T? defValue,
    required T Function(String json) fromJson,
    required String Function(T obj) toJson,
    String? defaultSuffix,
  }) {
    return SpObj(this, defaultValue: defValue, fromJson: fromJson, toJson: toJson, defaultSuffix: defaultSuffix);
  }
}
